#!/usr/local/bin/php -q
<?php
	define('MARKSMILIES_REPOSITORY_TYPE', 'url');

	function promptYN($question) 
	{
		if (!is_resource(@$GLOBALS['stdin'])) {
			$GLOBALS['stdin'] = fopen('php://stdin', 'r');
		}

		if (!is_resource(@$GLOBALS['stderr'])) {
			$GLOBALS['stderr'] = fopen('php://stderr', 'w');
		}
			
		do {
			fwrite($GLOBALS['stderr'], $question . " [Y/N] ");	
			$answer = strtolower(trim(fgets($GLOBALS['stdin'], 255)));
			$accepted = in_array($answer, array('y', 'n'));
		} while(!$accepted);
		
		return $answer == 'y';
	}

    class Fetcher 
	{
		public static function create($kind) 
		{
			switch ($kind) {
				case "url":
					$repository = new Fetcher_Url('http://marksmilies.googlecode.com/svn/trunk/');
					//    $repository->setProxy('192.100.100.100', '8080');
					return $repository;
				break;
				case "local":
					return new Fetcher_Local(dirname(__FILE__) . '/');
				break;
			}
		}
    }

	class Fetcher_Url 
	{
        private $proxyHost;
        private $proxyPort;
		private $base;

		public function __construct($base) 
		{
			$this->base = $base;
		}

        private function fetch($url) 
		{

            if($this->proxyHost && $this->proxyPort) {

                // via proxy
                $fp = fsockopen($this->proxyHost, $this->proxyPort);
                $host = parse_url($url);
                $host = $host['host'];
                fwrite($fp, 'GET ' . $url . ' HTTP/1.1' . "\n");
                fwrite($fp, 'Host: ' . $host . "\n\n");

                $ret = '';

                while($chunk = fread($fp, 1500)) {
                    $ret .= $chunk;
                }
                list($headers, $body) = explode("\r\n\r\n", $ret, 2);
                $headers = $this->parseHeaders($headers);
                if($headers['Status'] == 200)
                    return $body;
                else
                    return false;

            } else {
                return file_get_contents($url);
            }

        }

        public function setProxy($proxyHost, $proxyPort) 
		{
            $this->proxyHost = $proxyHost;
            $this->proxyPort = $proxyPort;
        }

        private function parseHeaders($headers) 
		{
            $ret = array();

            // split status
            list($statusLine, $headers) = explode("\n", $headers, 2);
            list(,$status,) = explode(' ', $statusLine, 3);
            $ret['Status'] = intval($status);

            foreach(explode("\n", $headers) as $line) {
                list($key, $value) = explode(':', $line, 2);
                list($key, $value) = explode(':', $line, 2);
                $ret[trim($key)] = trim($value);
            }
            return $ret;
        }

		public function getPluginList() 
		{
			// get list of all plugins
			$plugins = $this->fetch($this->base . 'plugins/');

			// <a href="DevNetwork_Sherbet.js">
			preg_match_all('/\<a href="(\w+\.js)"/', $plugins, $matches);	
			$plugins = $matches[1];
			return $plugins;
		}

		public function getMainScript() 
		{
			return $this->fetch($this->base . 'marksmilies.user.js');
		}

		public function getPlugin($name) 
		{
			return $this->fetch($this->base . 'plugins/' . $name);
		}
	}

	class Fetcher_Local 
	{
		private $base;
		public function __construct($dir) {
			$this->base = $dir;
		}

		public function getPluginList() {
			$plugins = glob($this->base . 'plugins/*');
			foreach ($plugins as &$plugin) {
				$plugin = str_replace($this->base . 'plugins/', '', $plugin);
			}
			return $plugins;
		}

		public function getMainScript() {
			return file_get_contents($this->base . 'marksmilies.user.js');
		}

		public function getPlugin($name) {
			return file_get_contents($this->base . 'plugins/' . $name);
		}
	}

    $repository = Fetcher::create(MARKSMILIES_REPOSITORY_TYPE);

	// get plugin list
	$plugins = $repository->getPluginList();

	// get the main script
	$mainScript = $repository->getMainScript();
	
	// split the license text out
	list($license, $mainScript) = explode('*/', $mainScript, 2);
	$license .= '*/';

	$pluginsMeta = array();
	$pluginsSrc = '';
	foreach ($plugins as $name) {
		if (!promptYN('Do you want to include plugin ' . $name . ' ?')) {
			continue;
		}
		$plugin = $repository->getPlugin($name);
		
		// split the license text out
		list($pluginLicense, $plugin) = explode('*/', $plugin, 2);
		$pluginLicense .= '*/';
		
		// if license differs from the one for main script, put it back
		if ($license != $pluginLicense) {
			$plugin = $pluginLicense . $plugin;
		}
		
		// find meta
		preg_match_all('#//\s*@(in|ex)clude.*#', $plugin, $matches);
		foreach ($matches[0] as $meta) {
			// remove it from plugin source
			$plugin = str_replace($meta, '', $plugin);
			$pluginsMeta[] = trim($meta);
		}
		$pluginsSrc .= "\n" . '// --- plugin ' . $name . ' begin ---' . "\n";
		$pluginsSrc .= $plugin;
		$pluginsSrc .= "\n" . '// --- plugin ' . $name . ' end ---' . "\n";
	}

	// insert required plugins
	$mainScript = preg_replace('#//\s*=+ Plugins should be placed here =+#', $pluginsSrc, $mainScript);

	// insert plugin's meta
	$mainScript = preg_replace('#//\s*==/UserScript==#', "\n" . implode("\n", $pluginsMeta) . "\n// ==/UserScript==\n", $mainScript);
	
	// put back the license for main script
	$mainScript = $license . $mainScript;
	
	echo $mainScript;	
?>
